package service

import (
	"context"
	"errors"
	"fmt"
	"time"

	"gitee.com/daonna/collab-manage-system/ent"
	"gitee.com/daonna/collab-manage-system/ent/attendancerecord"
	"gitee.com/daonna/collab-manage-system/ent/worktimesetting"
	"gitee.com/daonna/collab-manage-system/repository/db"
)

// 打卡请求
type CheckInOutRequest struct {
	Remarks string `json:"remarks"` // 可选备注
}

// 考勤记录结构
type AttendanceRecordDTO struct {
	ID           int64      `json:"id"`
	UserID       int64      `json:"user_id"`
	CheckInTime  *time.Time `json:"check_in_time"`
	CheckOutTime *time.Time `json:"check_out_time"`
	WorkDate     time.Time  `json:"work_date"`
	Status       string     `json:"status"`
	Remarks      string     `json:"remarks"`
	CreatedAt    time.Time  `json:"created_at"`
	UpdatedAt    time.Time  `json:"updated_at"`
}

// 月度统计
type MonthlyStatsDTO struct {
	Year         int `json:"year"`
	Month        int `json:"month"`
	WorkDays     int `json:"work_days"`
	AttendedDays int `json:"attended_days"`
	LateCount    int `json:"late_count"`
	EarlyLeave   int `json:"early_leave_count"`
	AbsentDays   int `json:"absent_days"`
}

// 上班打卡
func CheckIn(ctx context.Context, userID uint, req CheckInOutRequest) (*AttendanceRecordDTO, error) {
	client := db.GetDBClient()

	// 获取今天的日期（只保留年月日）
	today := time.Now().Truncate(24 * time.Hour)

	// 转换userID为int64类型，与数据库字段匹配
	userIDInt64 := int64(userID)

	// 检查是否已打卡
	record, err := client.AttendanceRecord().AttendanceRecord.
		Query().
		Where(
			attendancerecord.UserID(userIDInt64),
			attendancerecord.WorkDateEQ(today),
		).
		Only(ctx)

	// 如果已有记录且已打过上班卡
	if err == nil && record.CheckInTime != nil {
		return nil, errors.New("今日已打卡")
	}

	now := time.Now()
	status := "normal" // 默认正常

	// 获取工作时间设置
	timeSetting, err2 := client.WorkTimeSetting().WorkTimeSetting.
		Query().
		Where(worktimesetting.IsActive(true)).
		Order(ent.Desc(worktimesetting.FieldID)).
		First(ctx)

	if err2 != nil && !ent.IsNotFound(err2) {
		return nil, err2
	}

	// 判断是否迟到
	if err2 == nil { // 找到工作时间设置
		// 解析时间字符串，格式为HH:MM:SS
		layout := "15:04:05"
		checkInEndTimeStr := timeSetting.CheckInEnd
		checkInEndTime, parseErr := time.Parse(layout, checkInEndTimeStr)
		if parseErr != nil {
			return nil, parseErr
		}

		// 组合当前日期和时间
		checkInEndDateTime := time.Date(
			now.Year(), now.Month(), now.Day(),
			checkInEndTime.Hour(), checkInEndTime.Minute(), checkInEndTime.Second(),
			0, now.Location())

		if now.After(checkInEndDateTime) {
			status = "late"
		}
	}

	var createdRecord *ent.AttendanceRecord

	// 修复判断逻辑：正确处理记录不存在的情况
	if err != nil {
		if ent.IsNotFound(err) {
			// 创建新记录
			createdRecord, err = client.AttendanceRecord().AttendanceRecord.
				Create().
				SetUserID(userIDInt64).
				SetWorkDate(today).
				SetCheckInTime(now).
				SetStatus(attendancerecord.Status(status)).
				SetRemarks(req.Remarks).
				Save(ctx)

			if err != nil {
				return nil, err
			}
		} else {
			return nil, err // 其他错误直接返回
		}
	} else {
		// 更新已有记录（前面已排除了CheckInTime非空的情况）
		createdRecord, err = record.Update().
			SetCheckInTime(now).
			SetStatus(attendancerecord.Status(status)).
			SetRemarks(req.Remarks).
			Save(ctx)

		if err != nil {
			return nil, err
		}
	}

	return &AttendanceRecordDTO{
		ID:           createdRecord.ID,
		UserID:       createdRecord.UserID,
		CheckInTime:  createdRecord.CheckInTime,
		CheckOutTime: createdRecord.CheckOutTime,
		WorkDate:     createdRecord.WorkDate,
		Status:       string(createdRecord.Status),
		Remarks:      createdRecord.Remarks,
		CreatedAt:    createdRecord.CreatedAt,
		UpdatedAt:    createdRecord.UpdatedAt,
	}, nil
}

// 下班打卡
func CheckOut(ctx context.Context, userID uint, req CheckInOutRequest) (*AttendanceRecordDTO, error) {
	client := db.GetDBClient()

	// 获取今天的日期（只保留年月日）
	// 首先尝试精确匹配今天的日期
	now := time.Now()
	today := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)

	// 获取今日打卡记录
	record, err := client.AttendanceRecord().AttendanceRecord.
		Query().
		Where(
			attendancerecord.UserID(int64(userID)),
			attendancerecord.WorkDateEQ(today),
		).
		Only(ctx)
	fmt.Println("record", record)

	if err != nil {
		if ent.IsNotFound(err) {
			return nil, errors.New("请先完成上班打卡")
		}
		return nil, err
	}

	// 检查是否已下班打卡
	if record.CheckOutTime != nil {
		return nil, errors.New("今日已完成下班打卡")
	}

	status := record.Status // 保持原有状态

	// 获取工作时间设置
	timeSetting, err2 := client.WorkTimeSetting().WorkTimeSetting.
		Query().
		Where(worktimesetting.IsActive(true)).
		Order(ent.Desc(worktimesetting.FieldID)).
		First(ctx)

	if err2 != nil && !ent.IsNotFound(err2) {
		return nil, err2
	}

	// 判断是否早退
	if err2 == nil { // 找到工作时间设置
		// 解析时间字符串，格式为HH:MM:SS
		layout := "15:04:05"
		checkOutStartTimeStr := timeSetting.CheckOutStart
		checkOutStartTime, parseErr := time.Parse(layout, checkOutStartTimeStr)
		if parseErr != nil {
			return nil, parseErr
		}

		// 组合当前日期和时间
		checkOutStartDateTime := time.Date(
			now.Year(), now.Month(), now.Day(),
			checkOutStartTime.Hour(), checkOutStartTime.Minute(), checkOutStartTime.Second(),
			0, now.Location())

		// 如果早退并且不是已经迟到的状态，才标记为早退
		if now.Before(checkOutStartDateTime) && status != "late" {
			status = "early_leave"
		}
	}

	// 更新打卡记录
	updatedRecord, err := record.Update().
		SetCheckOutTime(now).
		SetStatus(status).
		SetRemarks(record.Remarks + " " + req.Remarks).
		Save(ctx)

	if err != nil {
		return nil, err
	}

	return &AttendanceRecordDTO{
		ID:           updatedRecord.ID,
		UserID:       updatedRecord.UserID,
		CheckInTime:  updatedRecord.CheckInTime,
		CheckOutTime: updatedRecord.CheckOutTime,
		WorkDate:     updatedRecord.WorkDate,
		Status:       string(updatedRecord.Status),
		Remarks:      updatedRecord.Remarks,
		CreatedAt:    updatedRecord.CreatedAt,
		UpdatedAt:    updatedRecord.UpdatedAt,
	}, nil
}

// 获取今日打卡状态
func GetTodayAttendance(ctx context.Context, userID uint) (*AttendanceRecordDTO, bool, error) {
	client := db.GetDBClient()

	// 获取今天的日期
	today := time.Now()
	today = time.Date(today.Year(), today.Month(), today.Day(), 0, 0, 0, 0, time.Local)

	// 查询今日打卡记录
	record, err := client.AttendanceRecord().AttendanceRecord.
		Query().
		Where(
			attendancerecord.UserID(int64(userID)),
			attendancerecord.WorkDateEQ(today),
		).
		Only(ctx)

	if err != nil {
		if ent.IsNotFound(err) {
			return nil, false, nil
		}
		return nil, false, err
	}

	return &AttendanceRecordDTO{
		ID:           record.ID,
		UserID:       record.UserID,
		CheckInTime:  record.CheckInTime,
		CheckOutTime: record.CheckOutTime,
		WorkDate:     record.WorkDate,
		Status:       string(record.Status),
		Remarks:      record.Remarks,
		CreatedAt:    record.CreatedAt,
		UpdatedAt:    record.UpdatedAt,
	}, true, nil
}

// 获取打卡历史记录
func GetAttendanceHistory(ctx context.Context, userID uint, year, month int) ([]AttendanceRecordDTO, error) {
	client := db.GetDBClient()

	// 计算月初和月末
	startOfMonth := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.Local)
	endOfMonth := startOfMonth.AddDate(0, 1, 0).Add(-time.Second)

	// 查询指定月份的打卡记录
	records, err := client.AttendanceRecord().AttendanceRecord.
		Query().
		Where(
			attendancerecord.UserID(int64(userID)),
			attendancerecord.WorkDateGTE(startOfMonth),
			attendancerecord.WorkDateLTE(endOfMonth),
		).
		Order(ent.Desc(attendancerecord.FieldWorkDate)).
		All(ctx)

	if err != nil {
		return nil, err
	}

	// 转换为返回格式
	result := make([]AttendanceRecordDTO, 0, len(records))
	for _, record := range records {
		result = append(result, AttendanceRecordDTO{
			ID:           record.ID,
			UserID:       record.UserID,
			CheckInTime:  record.CheckInTime,
			CheckOutTime: record.CheckOutTime,
			WorkDate:     record.WorkDate,
			Status:       string(record.Status),
			Remarks:      record.Remarks,
			CreatedAt:    record.CreatedAt,
			UpdatedAt:    record.UpdatedAt,
		})
	}

	return result, nil
}

// 获取月度考勤统计
func GetMonthlyAttendanceStats(ctx context.Context, userID uint, year, month int) (*MonthlyStatsDTO, error) {
	client := db.GetDBClient()

	// 计算月初和月末
	startOfMonth := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.Local)
	endOfMonth := startOfMonth.AddDate(0, 1, 0).Add(-time.Second)

	// 工作日计算 (简化版，假设周一到周五为工作日)
	workDays := 0
	for d := startOfMonth; d.Before(endOfMonth) || d.Equal(endOfMonth); d = d.AddDate(0, 0, 1) {
		if d.Weekday() != time.Saturday && d.Weekday() != time.Sunday {
			workDays++
		}
	}

	// 查询指定月份的打卡记录
	records, err := client.AttendanceRecord().AttendanceRecord.
		Query().
		Where(
			attendancerecord.UserID(int64(userID)),
			attendancerecord.WorkDateGTE(startOfMonth),
			attendancerecord.WorkDateLTE(endOfMonth),
		).
		All(ctx)

	if err != nil {
		return nil, err
	}

	// 统计数据
	attendedDays := len(records)
	lateCount := 0
	earlyLeaveCount := 0
	absentDays := 0

	for _, record := range records {
		if record.Status == "late" {
			lateCount++
		}
		if record.Status == "early_leave" {
			earlyLeaveCount++
		}
		if record.Status == "absent" {
			absentDays++
		}
	}

	// 创建统计结果
	stats := MonthlyStatsDTO{
		Year:         year,
		Month:        month,
		WorkDays:     workDays,
		AttendedDays: attendedDays,
		LateCount:    lateCount,
		EarlyLeave:   earlyLeaveCount,
		AbsentDays:   absentDays,
	}

	return &stats, nil
}
